import { _decorator, Component, Node, Material, renderer } from 'cc';
import {
    ToolsBrightnessContrast,
    ToolsLayerOpt,
    ToolsSeXiangBaoHeDuMingDu,
} from './PsBlendTools';
const { ccclass, property } = _decorator;

/**
 * 参数解析器
 * Name = AnalyticalParameters
 * DateTime = Mon Apr 11 2022 23:30:00 GMT+0800 (中国标准时间)
 * Author = 希格斯波色子
 * FileBasename = AnalyticalParameters.ts
 * FileBasenameNoExtension = AnalyticalParameters
 * URL = db://assets/psTools/script/AnalyticalParameters.ts
 * ManualUrl = https://docs.cocos.com/creator/3.4/manual/zh/
 *
 */

declare namespace __private {
    type _cocos_core_assets_material__MaterialPropertyFull = any;
}

export class AnalyticalParameters {
    static instance: AnalyticalParameters = null;
    static getInstance(): AnalyticalParameters {
        if (!AnalyticalParameters.instance)
            AnalyticalParameters.instance = new AnalyticalParameters();
        return AnalyticalParameters.instance;
    }

    private allDefinde: renderer.MacroRecord = null;
    private allProperty: {
        [name: string]:
            | __private._cocos_core_assets_material__MaterialPropertyFull
            | __private._cocos_core_assets_material__MaterialPropertyFull[];
    } = null;

    public analytical(
        shaders: Material[],
        copyShader: Material,
        param: (
            | ToolsLayerOpt
            | ToolsBrightnessContrast
            | ToolsSeXiangBaoHeDuMingDu
        )[],
    ) {
        this.allDefinde = {};
        this.allProperty = {};
        for (let i = 0; i < param.length; ++i) {
            if (param[i].name == 'ToolsLayerOpt') {
                let opt = param[i] as ToolsLayerOpt;
                this.addSelectOpt(opt.LAYER, 'LAYER', opt.LAYER.num);
            } else if (param[i].name == 'ToolsBrightnessContrast') {
                let opt = param[i] as ToolsBrightnessContrast;
                this.addSelectOpt(
                    opt.LiangDuDuiBiDu,
                    'LiangDuDuiBiDu',
                    opt.LiangDuDuiBiDu.num,
                );
            } else if (param[i].name == 'ToolsSeXiangBaoHeDuMingDu') {
                let opt = param[i] as ToolsSeXiangBaoHeDuMingDu;
                this.addSelectOpt(
                    opt.SeXiangBaoHeDuMingDu,
                    'SeXiangBaoHeDuMingDu',
                    opt.SeXiangBaoHeDuMingDu.num,
                );
            }
        }
        for (let i = 0; i < shaders.length; ++i) {
            let shader = shaders[i];
            if (!shader) continue;
            // shader.recompileShaders(this.allDefinde,0);
            shader.copy(copyShader, { defines: this.allDefinde });
            for (let name in this.allProperty) {
                shader.setProperty(name, this.allProperty[name]);
            }
        }
    }

    /**
     * 添加选择操作参数
     * @param selectOpt
     * @param optName
     * @param num
     */
    private addSelectOpt(selectOpt: any, optName: string, num: number) {
        let defindeName = optName + num;
        this.allDefinde[defindeName] = selectOpt.active;
        this.onSelect(selectOpt, num);
    }

    /**
     * 解析选择选项
     * @param info
     * @param num
     */
    private onSelect(info: any, num: number) {
        if (info.active) {
            //选中
            if ('activeOpt' in info) {
                this.addOptToLayout(info.activeOpt, num);
            }
        } else {
            //不选中
            if ('unActiveOpt' in info) {
                this.addOptToLayout(info.unActiveOpt, num);
            }
        }
    }

    /**
     * 解析选项参数
     * @param opt
     * @param num
     */
    private addOptToLayout(opt: any, num: number) {
        for (let keyStr in opt) {
            let info = opt[keyStr];
            switch (keyStr) {
                case 'u_dH':
                case 'u_dS':
                case 'u_dL':
                case 'brightness':
                case 'constrast':
                    this.allProperty[keyStr + num] = info.x;
                    break;
                case 'scale':
                case 'offset':
                case 'colorColor':
                case 'texture':
                    this.allProperty[keyStr + num] = info;
                    break;
                default: //这是选择选项
                    this.addSelectOpt(info, keyStr, num);
                    break;
            }
        }
    }
}
